import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity


def load_data(file_path):
    """
    从 CSV 文件中加载数据，并将其转换为用户-商品矩阵。
    :param file_path: CSV 文件的路径
    :return: 用户-商品矩阵，用户列表，商品列表
    """
    df = pd.read_csv(file_path)
    users = df['userid'].unique()
    goods = df['goodsid'].unique()
    print(users)

    # 创建用户和商品的索引映射
    user_index_map = {user: index for index, user in enumerate(users)}
    print(user_index_map)
    good_index_map = {good: index for index, good in enumerate(goods)}

    # 创建用户-商品交互矩阵（初始化为 0）
    data = np.zeros((len(users), len(goods)))


    # 填充用户-商品矩阵
    for _, row in df.iterrows():
        user_index = user_index_map[row['userid']]
        good_index = good_index_map[row['goodsid']]
        data[user_index][good_index] = 1  # 1 表示用户浏览过该商品

    return data, users, goods, user_index_map, good_index_map


def user_based_recommendation(data, user_index, top_n=8):
    """
    基于用户的协同过滤推荐。
    :param data: 用户-商品矩阵
    :param user_index: 目标用户的索引
    :param top_n: 推荐商品的数量
    :return: 推荐的商品列表
    """
    # 计算用户之间的余弦相似度
    user_similarity = cosine_similarity(data)

    # 目标用户与其他用户的相似度,从 user_similarity 矩阵中提取出目标用户（由 user_index 指定）与其他用户的相似度向量。
    target_user_similarity = user_similarity[user_index]

    # 排除用户自身的相似度
    target_user_similarity[user_index] = 0

    # 对相似度进行排序，找到最相似的用户
    similar_users_indices = np.argsort(target_user_similarity)[::-1]

    # 推荐商品列表
    recommended_goods = set()

    # 遍历最相似的用户，获取他们浏览过的商品
    for similar_user_index in similar_users_indices:
        similar_user_ratings = data[similar_user_index]

        # 遍历相似用户的商品，如果目标用户没有浏览该商品，则添加到推荐列表
        for good_index in range(len(similar_user_ratings)):
            if data[user_index][good_index] == 0 and similar_user_ratings[good_index] == 1:
                recommended_goods.add(good_index)

            # 达到推荐数量后退出循环
            if len(recommended_goods) >= top_n:
                break

        if len(recommended_goods) >= top_n:
            break

    return recommended_goods


def main(user_id):
    # 加载数据
    data, users, goods, user_index_map, good_index_map = load_data('D:\\household\\djhousehold\\csrec\\recommend.csv')

    # 假设我们要为第一个用户进行推荐
    try:
        user_index = user_index_map[user_id]  # 目标用户索引
    except KeyError:
        raise ValueError("User not found.")
    recommended_goods_indices = user_based_recommendation(data, user_index)

    # 将商品索引转换为商品 ID
    recommended_goods_ids = [goods[index] for index in recommended_goods_indices]

    # 输出推荐商品
    print(f"Recommended goods for user {users[user_index]}: {recommended_goods_ids}")

    return recommended_goods_ids

rec = main
